﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using ESRI.ArcGIS.ADF.Connection.AGS;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Server;
using ESRI.ArcGIS.esriSystem;
using EAGL.Core;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Display;

/// <summary>
/// Summary description for ContextManager
/// </summary>
namespace EAGL.Server
{
    public class ContextManager : IDisposable
    {
        private AGSServerConnection serverConnection;
        private string mapServiceName;
        private IMapServerObjects serverObjects;
        private IServerContext serverContext;
        private IServerObjectManager som;
        private IServerObjectAdmin admin;
        private IMapServer serverMapServer;
        private IMap serverMap;
        private IPageLayout serverLayout;


        public ContextManager(ConnectionManager connMan, string mapServiceName)
        {
            this.mapServiceName = mapServiceName;
            this.serverConnection = connMan.GetConnectionInstance();
            initServerObjects();
        }



        private void initServerObjects()
        {
            try
            {
                som = serverConnection.ServerObjectManager;
                admin = serverConnection.ServerObjectAdmin;
                serverContext = som.CreateServerContext(mapServiceName, "MapServer");
                serverMapServer = serverContext.ServerObject as IMapServer;
                serverObjects = serverMapServer as IMapServerObjects;
                serverMap = serverObjects.get_Map(serverMapServer.DefaultMapName);
                serverLayout = serverObjects.PageLayout;
            }
            catch (Exception ex)
            {
                throw new Exception("Error while initializing one of the server objects: " + ex.Message);
            }
        }

        public AGSServerConnection ConnectionInstance
        {
            get { return serverConnection; }
        }

        public IServerContext Context
        {
            get { return serverContext; }
        }

        public IMapServer MapServer
        {
            get { return serverMapServer; }
        }

        public IMapServerObjects2 MapServerObjects
        {
            get { return serverMapServer as IMapServerObjects2; }
        }

        public IServerObjectManager ObjectManager
        {
            get { return som; }
        }

        public IServerObjectAdmin ObjectAdmin
        {
            get { return admin; }
        }

        public IMap Map
        {
            get { return serverMap; }
        }

        public IPageLayout Layout
        {
            get { return serverLayout; }
        }

        /// <summary>
        /// creates (clones) and object in the local context same as the object in
        /// the server context using serialization
        /// 
        /// </summary>
        /// <param name="proxyObject"></param>
        /// <returns></returns>
        public static IPersistStream CopyToHere(IServerContext context, IPersistStream proxyObject)
        {
            // serialize the server context object
            IXMLStream stream = context.CreateObject("esriSystem.XmlStream") as IXMLStream;
            proxyObject.Save(stream as IStream, 0);

            byte[] bytes = stream.SaveToBytes();
            object o = new MapClass();
            SerializationManager.DeserializeUsingPersistStream(bytes, ref o);
            return o as IPersistStream;
            // create new local object and fill it using the bytes from the server object
        }

        public object CopyToContext_OS(object o, Guid g)
        {
            TObjectStreamSerializer serializer = new TObjectStreamSerializer();
            byte[] bytes = serializer.Serialize(o);
            object obj = serializer.Deserialize(bytes, this.Context, g);
            return obj;
        }

        public object CopyToContext_PS(IPersistStream ps, string CLSID)
        {
            TPersistStreamSerializer serializer = new TPersistStreamSerializer();
            byte[] bytes = serializer.Serialize(ps);
            return serializer.Deserialize(bytes, this.Context, CLSID);
        }





        #region IDisposable Members

        public void Dispose()
        {
            if (serverContext != null)
                serverContext.ReleaseContext();
        }

        #endregion
    }
}